<script lang="ts" setup>
import type { ModalState } from '@vben/common-ui';
import type { TodosInfo } from '@vben/types';

import type { VbenFormProps } from '#/adapter/form';
import type { VxeGridProps } from '#/adapter/vxe-table';

import { ref } from 'vue';

import { Page, useVbenModal } from '@vben/common-ui';

import { Button, Popconfirm, Tag } from 'ant-design-vue';
import dayjs from 'dayjs';

import { useVbenForm } from '#/adapter/form';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import {
  addTodosInfoApi,
  deleteTodosInfoApi,
  getTodosInfoApi,
  updateTodosInfoApi,
} from '#/api/tools';

/**
 * 表格搜索组件（表单）的参数设置
 */
const formOptions: VbenFormProps = {
  // 默认展开
  collapsed: false,
  schema: [
    {
      component: 'Select',
      componentProps: {
        allowClear: true,
        options: [
          {
            label: '未完成',
            value: '未完成',
          },
          {
            label: '已完成',
            value: '已完成',
          },
          {
            label: '已到期',
            value: '已到期',
          },
        ],
        placeholder: '请选择',
      },
      defaultValue: '未完成',
      fieldName: 'status',
      label: '完成状态',
    },
    {
      component: 'Select',
      componentProps: {
        allowClear: true,
        options: [
          {
            label: '最低',
            value: 1,
          },
          {
            label: '低',
            value: 2,
          },
          {
            label: '普通',
            value: 3,
          },
          {
            label: '高',
            value: 4,
          },
          {
            label: '最高',
            value: 5,
          },
        ],
        placeholder: '请选择',
      },
      fieldName: 'priority',
      label: '优先级',
    },
    {
      component: 'Input',
      componentProps: {
        placeholder: '请输入标题',
      },
      defaultValue: '',
      fieldName: 'title',
      label: '标题',
    },
    {
      component: 'Input',
      componentProps: {
        placeholder: '请输入任务详情',
      },
      defaultValue: '',
      fieldName: 'description',
      label: '任务详情',
    },
  ],
  // 控制表单是否显示折叠按钮
  showCollapseButton: false,
  submitButtonOptions: {
    content: '查询',
  },
  // 是否在字段值改变时提交表单
  submitOnChange: true,
  // 按下回车时是否提交表单
  submitOnEnter: false,
  wrapperClass: 'grid grid-cols-5',
};
/**
 * 表格的参数设置
 */
const gridOptions: VxeGridProps<TodosInfo> = {
  columns: [
    { type: 'checkbox', width: 50 },
    { title: '序号', type: 'seq', width: 50 },
    {
      field: 'priority',
      title: '优先级',
      sortable: true,
      width: 100,
      slots: { default: 'priority' },
    },
    { field: 'title', title: '标题', width: 200 },
    { field: 'description', title: '任务描述' },
    { field: 'createAt', title: '创建时间', sortable: true, width: 200 },
    { field: 'dueDate', title: '截止日期', sortable: true, width: 200 },
    {
      field: 'status',
      title: '任务状态',
      slots: { default: 'status' },
      width: 100,
    },
    {
      field: 'action',
      slots: { default: 'action' },
      title: '操作',
      width: 200,
    },
  ],
  keepSource: true,
  proxyConfig: {
    sort: true,
    ajax: {
      query: async ({ page, sort }, formValues) => {
        // message.success(`Query params: ${JSON.stringify(formValues)}`);
        return await getTodosInfoApi({
          page: page.currentPage,
          pageSize: page.pageSize,
          sortBy: sort.field,
          sortOrder: sort.order,
          ...formValues,
        });
      },
    },
  },
  toolbarConfig: {
    // 是否显示搜索表单控制按钮
    // @ts-ignore 正式环境时有完整的类型声明
    search: true,
    custom: true,
    // export: true,
    // import: true,
    refresh: true,
    zoom: true,
  },
  sortConfig: {
    remote: true,
    trigger: 'cell',
  },
  height: 'auto',
};
/**
 * 表格的变量对象
 */
const [Grid, gridApi] = useVbenVxeGrid({ formOptions, gridOptions });

const todoId = ref(-1); // 当前正在编辑的待办事项的id
const title = ref<string>(''); // 当前弹出框的标题
const spinning = ref<boolean>(false); // 加载组件的状态
const statusColor = ref<Record<string, string>>({
  已完成: 'green',
  未完成: 'blue',
  已到期: 'red',
}); // 状态的颜色map
const priorityMap = ref<Record<string, Record<string, string>>>({
  '1': { value: '最低', color: 'blue' },
  '2': { value: '低', color: 'cyan' },
  '3': { value: '普通', color: 'green' },
  '4': { value: '高', color: 'orange' },
  '5': { value: '最高', color: 'red' },
});
/**
 * 弹出框/表单的提交事件
 * @param values 表单的数据值
 */
const submitModal = async (values: Record<any, any>) => {
  spinning.value = true;

  const data: TodosInfo = {
    title: values.title,
    description: values.description,
    dueDate: values.dueDate ? values.dueDate.format('YYYY-MM-DD') : '',
    priority: values.priority,
    status: values.status,
    createAt: '',
    id: todoId.value,
    username: '',
  };

  if (title.value === '新增') {
    await addTodosInfoApi(data);
  } else if (title.value === '编辑') {
    await updateTodosInfoApi(data);
  }
  await gridApi.query();
  spinning.value = false;
};
/**
 * 弹出框内表单的参数设置和变量对象
 */
const [Form, formApi] = useVbenForm({
  commonConfig: {
    // 所有表单项
    componentProps: {
      class: 'w-full',
    },
  },
  handleSubmit: submitModal,
  layout: 'horizontal',
  schema: [
    {
      // 组件需要在 #/adapter.ts内注册，并加上类型
      component: 'Input',
      // 对应组件的参数
      componentProps: {
        placeholder: '请输入',
      },
      // 字段名
      fieldName: 'title',
      // 界面显示的label
      label: '任务标题',
      rules: 'required',
    }, // 标题
    {
      component: 'Textarea',
      componentProps: {
        placeholder: '请输入',
        autoSize: true,
      },
      fieldName: 'description',
      label: '任务描述',
      rules: 'required',
    }, // 任务描述
    {
      component: 'Select',
      componentProps: {
        allowClear: true,
        filterOption: true,
        options: [
          {
            label: '最低',
            value: 1,
          },
          {
            label: '低',
            value: 2,
          },
          {
            label: '普通',
            value: 3,
          },
          {
            label: '高',
            value: 4,
          },
          {
            label: '最高',
            value: 5,
          },
        ],
        placeholder: '请选择',
      },
      defaultValue: 3,
      fieldName: 'priority',
      label: '优先级',
      rules: 'selectRequired',
    }, // 优先级
    {
      component: 'Select',
      componentProps: {
        allowClear: true,
        filterOption: true,
        options: [
          {
            label: '未完成',
            value: '未完成',
          },
          {
            label: '已完成',
            value: '已完成',
          },
          {
            label: '已到期',
            value: '已到期',
          },
        ],
        placeholder: '请选择',
      },
      defaultValue: '未完成',
      fieldName: 'status',
      label: '任务状态',
      rules: 'selectRequired',
    }, // 任务状态
    {
      component: 'DatePicker',
      defaultValue: undefined,
      fieldName: 'dueDate',
      label: '截止日期',
    }, // 截止日期
  ],
  wrapperClass: 'grid-cols-1',
  showDefaultActions: false,
});
/**
 * 弹出框的参数设置和变量对象
 */
const [Modal, modalApi] = useVbenModal({
  onConfirm: async () => {
    await formApi.validateAndSubmitForm();
    modalApi.close();
  },
});
/**
 * 弹出框的打开事件
 * @param props 状态参数，表示状态的更改
 * @param row 行数据，用于编辑数据
 */
const handleModal = (
  props: ModalState,
  row: Record<string, any> | undefined = undefined,
) => {
  if (row) {
    todoId.value = row.id;
    formApi.setValues({
      ...row,
      dueDate: row.dueDate === '' ? '' : dayjs(row.dueDate, 'YYYY-MM-DD'),
    });
  }
  title.value = props.title ?? '';
  modalApi.setState(props);
  modalApi.open();
};
/**
 * 更新数据
 * @param row 行数据，获取数据的更新
 */
const updateStatus = async (row: Record<any, any>) => {
  if (row.status === '已完成') {
    row.status = '未完成';
  } else if (row.status === '未完成' || row.status === '已到期') {
    row.status = '已完成';
  }
  const data: TodosInfo = {
    title: row.title,
    description: row.description,
    dueDate: row.dueDate,
    priority: row.priority,
    status: row.status,
    createAt: '',
    id: row.id,
    username: '',
  };
  await updateTodosInfoApi(data);
  gridApi.query();
};
/**
 * 根据id删除待办事项
 * @param id 行数据（待办事项）的id
 */
const deleteTodoById = async (id: number) => {
  await deleteTodosInfoApi([id]);
  gridApi.query();
};
/**
 * 删除选中的待办事项
 */
const deleteTodoBySelect = async () => {
  const ids = gridApi.grid
    .getCheckboxRecords()
    .map((item) => item.id)
    .filter((id): id is number => typeof id === 'number');
  if (ids.length === 0) return;
  await deleteTodosInfoApi(ids);
  gridApi.query();
};
</script>

<template>
  <Page auto-content-height>
    <Grid table-title="待办事项">
      <template #toolbar-tools>
        <Button
          class="mr-2"
          type="primary"
          @click="() => handleModal({ title: '新增' })"
        >
          新增
        </Button>
        <Popconfirm
          class="mr-2"
          title="是否删除？"
          ok-text="是"
          cancel-text="否"
          @confirm="deleteTodoBySelect"
        >
          <Button> 删除 </Button>
        </Popconfirm>
      </template>
      <template #priority="{ row }">
        <Tag :color="priorityMap[row.priority]?.color">
          {{ priorityMap[row.priority]?.value }}
        </Tag>
      </template>
      <template #status="{ row }">
        <Tag :color="statusColor[row.status]">
          {{ row.status }}
        </Tag>
      </template>
      <template #action="{ row }">
        <Button type="link" @click="() => handleModal({ title: '编辑' }, row)">
          编辑
        </Button>
        <Popconfirm
          :title="row.status === '已完成' ? '是否启用？' : '是否完成？'"
          ok-text="是"
          cancel-text="否"
          @confirm="() => updateStatus(row)"
        >
          <Button type="link">
            {{ row.status === '已完成' ? '启用' : '完成' }}
          </Button>
        </Popconfirm>
        <Popconfirm
          title="是否删除？"
          ok-text="是"
          cancel-text="否"
          @confirm="() => deleteTodoById(row.id)"
        >
          <Button type="link">删除</Button>
        </Popconfirm>
      </template>
    </Grid>
    <Modal :confirm-loading="spinning">
      <Form />
    </Modal>
  </Page>
</template>
